<template>
  <div class="my-scrollbar">
    <div class="my-scrollbar__container" @scroll="handleContainerScroll" ref="container">
      <div class="my-scrollbar__content" ref="content">
        <slot></slot>
      </div>
    </div>
    <div class="my-scrollbar__rail vertical">
      <div class="my-scrollbar__bar" @mousedown="handleBarMousedown" ref="bar" :style="barStyle"></div>
    </div>
    <!-- <div class="my-scrollbar__rail horizontal">
      <div class="my-scrollbar__bar" @mousedown="handleBarMousedown" ref="bar"></div>
    </div>-->
  </div>
</template>

<script>
export default {
  name: "MyScrollbar",
  data() {
    return {
      barStyle: {
        transform: "translateY(0%)",
        height: "0%",
      },
    };
  },
  mounted() {
    this.initMutationObserver();
    this.calcBarHeight();
  },
  beforeDestroy() {
    this.contentOb && this.contentOb.disconnect();
  },
  methods: {
    initMutationObserver() {
      this.contentOb = new MutationObserver(() => {
        this.calcBarHeight();
      });
      this.contentOb.observe(this.$refs.content, {
        characterData: true,
        childList: true,
        subtree: true,
      });
    },
    scrollTo(distance) {
      this.$refs.container.scrollTop = distance;
    },
    // scrollTo(distance) {
    //   this.$refs.container.scrollTop = distance;
    //   if (this.scrolling) return;
    //   this.scrolling = true;
    //   this.scrollDistance = distance;
    //   this.startScrollTime = Date.now();
    //   requestAnimationFrame(this.scrollAnimation);
    // },
    // scrollAnimation() {
    //   const progress = (Date.now() - this.startScrollTime) / 300;
    //   const distance = progress * this.scrollDistance;
    //   this.$refs.container.scrollTop = distance;
    //   if (progress < 1) {
    //     requestAnimationFrame(this.scrollAnimation);
    //   } else {
    //     this.scrolling = false;
    //   }
    // },
    handleBarMousedown(e) {
      document.addEventListener("mousemove", this.handleDocMousedown);
      document.addEventListener("mouseup", this.handleDocMouseupdown);

      this.barStartTop = e.clientY - this.$refs.bar.getBoundingClientRect().top;
    },
    handleDocMousedown(e) {
      let { scrollHeight, clientHeight } = this.$refs.container;
      let offset = e.clientY - this.$refs.container.getBoundingClientRect().top;
      let percentage = (offset - this.barStartTop) / clientHeight;

      this.$refs.container.scrollTop = percentage * scrollHeight;
    },
    handleDocMouseupdown() {
      document.removeEventListener("mousemove", this.handleDocMousedown);
    },
    calcBarHeight() {
      let { clientHeight, scrollHeight } = this.$refs.container;
      let height = (clientHeight / scrollHeight) * 100;
      this.barStyle.height = height < 100 ? height + "0%" : "0%";
    },
    handleContainerScroll() {
      let { scrollTop, clientHeight } = this.$refs.container;
      this.barStyle.transform = `translateY(${
        (scrollTop / clientHeight) * 100
      }%)`;
    },
  },
};
</script>

<style lang="scss">
.my-scrollbar {
  overflow: hidden;
  position: relative;

  .my-scrollbar__container {
    width: 100%;
    overflow: scroll;
    height: 100%;
    max-height: inherit;
    -ms-overflow-style: none;
    scrollbar-width: none;

    &::-webkit-scrollbar,
    &::-webkit-scrollbar-track-piece,
    &::-webkit-scrollbar-thumb {
      width: 0;
      height: 0;
      display: none;
    }
  }

  .my-scrollbar__rail {
    position: absolute;
    right: 2px;
    bottom: 2px;
    z-index: 1;
    opacity: 0;
    transition: opacity 0.12s ease-out;

    .my-scrollbar__bar {
      position: relative;
      border-radius: 4px;
      cursor: pointer;
      user-select: none;
      background-color: rgba($color: #7e8299, $alpha: 0.2);
      transition: background-color 0.3s;

      &:hover {
        background-color: rgba($color: #7e8299, $alpha: 0.4);
      }
    }

    &.vertical {
      width: 6px;
      top: 2px;

      &.my-scrollbar__bar {
        width: 100%;
      }
    }

    &.horizontal {
      height: 6px;
      left: 2px;
      &.my-scrollbar__bar {
        height: 100%;
      }
    }
  }

  &:hover .my-scrollbar__rail,
  &:active .my-scrollbar__rail,
  &:focus .my-scrollbar__rail {
    opacity: 1;
  }

  .my-scrollbar__content {
    min-width: 100%;
    width: fit-content;
  }
}
</style>